﻿using GeometRi;
using SolidWorks.Interop.sldworks;
using SolidWorks.Interop.swconst;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SolidWorksStudy.Models
{
    public class SheetMetal
    {
        public List<CircleHoleModel> CircleHoles { get; set; }
        public List<SlotHoleModel> SlotHoles { get; set; }
        SldWorks swApp;
        ModelDoc2 swModel; // 当前文档对象
        PartDoc prtDoc;
        SelectionMgr swMgr;
        Coord3d baseCoord;      // 参考坐标系
        FeatureManager featMgr; // 特征管理器对象
        
        public SheetMetal()
        {
            swApp = Utility.ConnectToSolidWorks();
            swApp.CommandInProgress = true;
            swModel = (ModelDoc2)swApp.ActiveDoc;
            featMgr = swModel.FeatureManager;
        }
        // 输出铜排信息
        public void ExportInfo()
        {

            prtDoc = (PartDoc)swModel;
            swMgr = swModel.ISelectionManager;
            Face2 bigestFace = GetBigestFace();
            // 创建参考坐标系
            baseCoord = CreateCoord(bigestFace);

            RecodBendLineInfo();

            RecordHoleInfo(bigestFace);


            swApp.CommandInProgress = false;
        }

        private void RecodBendLineInfo()
        {
            Feature feat;
            SheetMetalFolder sheetMetalFolder = (SheetMetalFolder)featMgr.GetSheetMetalFolder();
            feat = (Feature)sheetMetalFolder.GetFeature();
            object[] featArray;

            Debug.Print("Sheet metal folder name: " + feat.Name);
            Debug.Print("  Number of sheet metal features in the folder: " + sheetMetalFolder.GetSheetMetalCount());
            featArray = (object[])sheetMetalFolder.GetSheetMetals();
            for (int i = featArray.GetLowerBound(0); i <= featArray.GetUpperBound(0); i++)
            {
                feat = (Feature)featArray[i];
                Debug.Print("    " + feat.Name);
            }


        }

        /// <summary>
        /// 此函数用于获取最大面
        /// </summary>
        /// <returns>该铜排最大的面</returns>
        private Face2 GetBigestFace()
        {

            List<Face2> faceList = new List<Face2>();
            // 拿到最大面积的Face对象
            object[] bodies = (object[])prtDoc.GetBodies2((int)swBodyType_e.swSolidBody, false);


            swModel.ClearSelection();
            Body2 body = (Body2)bodies[0];

            // 此步骤是获取最大面，再选取相切获得铜排面
            object[] faces = (object[])body.GetFaces();
            var validFaces = faces
                .Where(face => face != null && face is Face2)
                .Cast<Face2>();

            Face2 bigFace = validFaces.OrderByDescending(face => face.GetArea()).FirstOrDefault();
            return bigFace;
        }


        /// <summary>
        /// 统计所传Face对象所在的铜排 中 包含的圆孔、腰孔信息，存入到属性里
        /// </summary>
        /// <param name="bigestFace">传该铜排体的最大面</param>
        private void RecordHoleInfo(Face2 bigestFace)
        {
            this.CircleHoles = new List<CircleHoleModel>();
            this.SlotHoles = new List<SlotHoleModel>();

            // 统计铜排信息，获得圆孔、腰孔、折弯线坐标
            Entity faceEnt = (Entity)bigestFace;
            faceEnt.Select(true);
            swModel.SelectTangency();
            int selectCount = swMgr.GetSelectedObjectCount();
            List<Face2> sheetMetalFaces = new List<Face2>();
            for (int i = 1; i <= selectCount; i++)
            {
                Face2 faceSelect = (Face2)swMgr.GetSelectedObject6(i, -1);
                sheetMetalFaces.Add(faceSelect);
            }
            swModel.ClearSelection();
            // 统计Face信息：孔、BendLine
            foreach (Face2 face in sheetMetalFaces)    // 遍历切面上所有的Face2对象
            {
                // 将面的向量赋值
                Vector3d faceVector3D = new Vector3d((double[])face.Normal);

                faceEnt = (Entity)face;
                faceEnt.Select(false);  // 标记易于观察

                object[] loops = (object[])face.GetLoops();

                foreach (Loop2 loop in loops)       //面上面的环（Loop）对象
                {
                    bool isLoopOuter = loop.IsOuter();

                    // 如果是最外边包围框 跳过
                    if (isLoopOuter)
                    {
                        object[] vertices = (object[])loop.GetVertices();   //获得所有环的顶点
                        continue;
                    }

                    object[] edges = (object[])loop.GetEdges();

                    // 此Loop只有一个Edge对象，极有可能是个圆环
                    if (edges.Length == 1)
                    {
                        Edge edge = (Edge)edges[0];
                        CurveParamData curveParama = edge.GetCurveParams3(); // 获取曲线类型
                        Curve curve = (Curve)edge.GetCurve();
                        if (curve.IsCircle()) // 如果是圆 
                        {
                            // 记录当前信息
                            double[] circleParama = (double[])curve.CircleParams;
                            double centerX = Math.Round(circleParama[0] * 1000, 2);    // 保留六位小数
                            double centerY = Math.Round(circleParama[1] * 1000, 2);
                            double centerZ = Math.Round(circleParama[2] * 1000, 2);
                            double cirleRadius = Math.Round(circleParama[6] * 1000, 2);

                            Point3d circleCenterPoint = new Point3d(centerX, centerY, centerZ); // 获得初始坐标，即Solidworks当中的坐标
                            Point3d convertPoint = circleCenterPoint.ConvertTo(baseCoord);    // 转到相对坐标来

                            loop.Select(null, false, null);

                            // 构建圆孔对象
                            CircleHoleModel circleHoleModel = new CircleHoleModel(convertPoint, cirleRadius);


                            this.CircleHoles.Add(circleHoleModel);
                            //Debug.Print($"Circel Added: MM baseCoord Pos:[{circleCenterPoint.X}、{circleCenterPoint.Y}、{circleCenterPoint.Z}];Global Pos:[{circleCenterPoint.X}、{circleCenterPoint.Y}、{circleCenterPoint.Z}]");
                            Debug.Print($"Circel Added: MM baseCoord Pos:[{circleCenterPoint.X}、{circleCenterPoint.Y}、{circleCenterPoint.Z}];Global Pos:[{circleCenterPoint.X}、{circleCenterPoint.Y}、{circleCenterPoint.Z}]");

                            continue;
                        }
                    }

                    else if (edges.Length == 4) // 此Loop有四个Edge对象，可能是腰孔，也有可能是其他具有四条边的图形
                    {
                        int arcCount = 0;
                        int lineCount = 0;
                        Curve[] circleCurves = new Curve[2];
                        Curve[] lineCurves = new Curve[2];
                        for (int i = 0; i < edges.Length; i++)
                        {
                            Edge edge = edges[i] as Edge;
                            Curve curve = (Curve)edge.GetCurve();
                            if (curve != null)
                            {
                                if (curve.IsCircle())
                                {
                                    circleCurves[arcCount] = curve;
                                    arcCount++;
                                }
                                else if (curve.IsLine())
                                {
                                    lineCurves[lineCount] = curve;
                                    lineCount++;
                                }
                                else
                                {
                                    Debug.Print("Curve is not Line or Circle ");
                                }
                            }
                        }
                        if (arcCount == lineCount && arcCount == 2) //槽口有两条线，两个半圆
                        {

                            double[] circleParadata0 = (double[])circleCurves[0].CircleParams;
                            double[] circleParadata1 = (double[])circleCurves[1].CircleParams;


                            double radius = Math.Round(circleParadata0[6] * 1000, 2);  // 槽口的半径1
                            double radius2 = Math.Round(circleParadata1[6] * 1000, 2);  // 槽口的半径2
                            if (radius != radius2)
                            {
                                Debug.Print("两圆两线，半径不相同，非槽口");
                                continue;
                            }
                            Debug.Print("槽口");
                            loop.Select(null, false, null);

                            Point3d slotPoint1 = new Point3d(Math.Round(circleParadata0[0] * 1000, 2), Math.Round(circleParadata0[1] * 1000, 2), Math.Round(circleParadata0[2] * 1000, 2));
                            Point3d slotPoint2 = new Point3d(Math.Round(circleParadata1[0] * 1000, 2), Math.Round(circleParadata1[1] * 1000, 2), Math.Round(circleParadata1[2] * 1000, 2));

                            Point3d slotPoint1Convert = slotPoint1.ConvertTo(baseCoord);
                            Point3d slotPoint2Convert = slotPoint2.ConvertTo(baseCoord);

                            SlotHoleModel slotHole = new SlotHoleModel(slotPoint1Convert, slotPoint2Convert, radius);

                            this.SlotHoles.Add(slotHole);
                            Debug.Print($"SlotHole Added(MM):  Pos on base coord:[{slotHole.startPoint.X}、{slotHole.startPoint.Y}]");

                        }
                    }
                }

            }
        }
        private Coord3d CreateCoord(Face2 bigestFace)
        {
            int edgeCount = bigestFace.GetEdgeCount(); // 获得该最大面包含的Edge（边界）数量
            object[] faceEdges = (object[])bigestFace.GetEdges(); // 获得面包含的Edge对象

            // 创建一个包含Edge和对应长度的元组数组
            var edgeLengths = faceEdges.Select(objEdge =>
            {
                Edge edge = (Edge)objEdge;
                Curve curve = edge.IGetCurve();
                curve.GetEndParams(out double start, out double end, out bool isClosed, out bool isPeriodic);
                double length = curve.GetLength3(start, end);
                return (edge, length);
            }).ToArray();

            // 根据长度进行降序排序
            edgeLengths = edgeLengths.OrderByDescending(x => x.length).ToArray();
            Edge firstEdge = edgeLengths[0].edge;   //最大的Edge
            Edge secondEdge = edgeLengths[1].edge;  // 与最大边平行的Edge，这两条边一样大

            // 构建坐标轴需要的点、向量
            Vertex coordStartVertex = firstEdge.IGetStartVertex();  // 点1：坐标轴原点
            double[] startPoint = (double[])coordStartVertex.GetPoint();
            Point3d pointOrigin = new Point3d(Math.Round(startPoint[0] * 1000, 2), Math.Round(startPoint[1] * 1000, 2), Math.Round(startPoint[2] * 1000, 2));
            //Point3d pointOrigin = new Point3d(startPoint[0] , startPoint[1], startPoint[2]);



            Vertex coordEndVertex = firstEdge.IGetEndVertex();    // 点2：x轴上的一个点
            double[] endPoint = (double[])coordEndVertex.GetPoint();
            Point3d pointOnX = new Point3d(Math.Round(endPoint[0] * 1000, 2), Math.Round(endPoint[1] * 1000, 2), Math.Round(endPoint[2] * 1000, 2));
            //Point3d pointOnX = new Point3d(endPoint[0], endPoint[1], endPoint[2]);

            Vertex vertexOnXYPlane = secondEdge.IGetStartVertex();   // 点3：x轴和y轴形成面上的一点
            double[] pointOnXYPlaneArray = (double[])vertexOnXYPlane.GetPoint();
            Point3d pointOnXYPlane = new Point3d(Math.Round(pointOnXYPlaneArray[0] * 1000, 2), Math.Round(pointOnXYPlaneArray[1] * 1000, 2), Math.Round(pointOnXYPlaneArray[2] * 1000, 2));
            //Point3d pointOnXYPlane = new Point3d(pointOnXYPlaneArray[0], pointOnXYPlaneArray[1], pointOnXYPlaneArray[2]);


            // 创建 Coord3d 对象
            Coord3d coord = new Coord3d(pointOrigin, pointOnX, pointOnXYPlane, "新参考基准轴");
            bigestFace.Highlight(true);

            //Point3d p1 = new Point3d(0,0,0,coord);

            //Debug.Print(p1.ToString(coord));

            return coord;

        }

    }

}
